home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’93
/
OK, What was that again?
/
Extension
/
Backup
/
OSUtilsSup.c
< prev
Wrap
Text File
|
1992-06-18
|
6KB
|
236 lines
/**************************************************************************************
FILENAME
OSUtilsSup.c
DESCRIPTION
A colection of utilities to aid in the patching of traps.
COPYRIGHT
Copyright © Apple Computer, Inc. 1990
All rights reserved.
ROUTINES
EXTERNAL
PatchTrap
RestoreTrap
MODIFICATION HISTORY
01/05/90 Sean Parent
1) Ported from OpSysUtilSup.p and updated with lots of new wizzies.
03/04/90 sp
1) Moved into Pack2.
2) Added check for System 7.0.
**************************************************************************************/
#pragma segment Utilities
#define Pack2Internal
/**************************************************************************************
INCLUDES
**************************************************************************************/
#ifndef __TYPES__
#include <Types.h>
#endif
#ifndef __MEMORY__
#include <Memory.h>
#endif
#ifndef __ERRORS__
#include <Errors.h>
#endif
#ifndef __TRAPS__
#include <Traps.h>
#endif
#ifndef __OSUTILS__
#include <OSUtils.h>
#endif
#include "OSUtilsSup.h"
/*<FF>*/
/**************************************************************************************
TYPEDEFS
**************************************************************************************/
short NumToolboxTraps(void)
{
if (GetToolboxTrapAddress(_InitGraf) == GetToolboxTrapAddress(0xAA6E)) {
return 0x0200;
} else return 0x0400;
}
TrapType GetTrapType(short theTrap)
{
enum { trapMask = 0x0800 };
if (theTrap & trapMask) return ToolTrap;
else return OSTrap;
}
Boolean TrapEntryAvailable(short theTrap, TrapType tType)
{
/* Note: What about autopop? */
if ((tType == ToolTrap) && ((theTrap & 0x03FF) >= NumToolboxTraps())) return false;
#ifdef oldSupport
/* Is the trap in part of the table that maybe overlayed? */
if (((tType == ToolTrap) && ((theTrap & 0x03FF) < 0x0100)) || (tType == OSTrap)) {
long address = GetTrapAddress(theTrap, trapType);
/* Is the trap table overlayed or are the traps duplicates and not unimplemented? */
if ((GetToolboxTrapAddress(0xA000) == GetOSTrapAddress(0xA800))
|| ((address == NGetTrapAddress(theTrap, !trapType))
&& (address != GetToolboxTrapAddress(_Unimplemented)))) {
/* Is it a valid trap type */
theTrap &= 0x00FF;
if (((theTrap < 0x0050) || (theTrap == 0x0054) || (theTrap == 0x0057))
!= (tType == OSTrap)) return false;
}
}
#endif
return true;
}
Boolean TrapAvailable(short theTrap)
{
TrapType tType;
tType = GetTrapType(theTrap);
if (!TrapEntryAvailable(theTrap, tType)) return false;
return NGetTrapAddress(theTrap, tType) != GetToolboxTrapAddress(_Unimplemented);
}
void FlushInstructionRange(void* address, long count)
{
#pragma unused (address, count)
FlushInstructionCache();
#if false
if (TrapAvailable(_HWPriv)) {
if (FlushCodeCacheRange(address, count) == hwParamErr) {
FlushInstructionCache();
}
} else if (TrapAvailable(_FlushCodeCache)) FlushCodeCache();
#endif
}
/*<FF>*/
/**************************************************************************************
ROUTINE
PatchTrap
DESCRIPTION
Given a trap number and a routine address install a patch. If there is no entry in
the trap table for trap type (older machine) then return nil. The patchType may be
override and/or removable. If the patch is an override then nil will be returned if
the routine is already implemented (This is useful to avoid patching a trap twice).
If the patch is removeable then a reference will be returned to a block that is used
to unhook the patch on removal. The address of the previouse routine is returned
in oldRoutine or nil if it was unimplemented.
**************************************************************************************/
#define require(assertion, handler) \
do { \
if (assertion) ; else goto handler; \
} while (false)
#define JMP 0x4EF9
Patch PatchTrap( ProcPtr* oldRoutine,
short theTrap,
ProcPtr routine,
PatchType patchType)
{
ProcPtr tempRoutine;
TrapType tType;
tType = GetTrapType(theTrap);
require(TrapEntryAvailable(theTrap, tType), TrapEntryAvailable);
tempRoutine = (ProcPtr)NGetTrapAddress(theTrap, tType);
if (oldRoutine) *oldRoutine = tempRoutine;
if (*oldRoutine == NGetTrapAddress(_Unimplemented, ToolTrap)) {
*oldRoutine = nil;
}
require(!((patchType & patchOverride) && *oldRoutine), TrapImplemented);
if (patchType & patchRemovable) {
SPatch* patch = (SPatch*)NewPtrSys(sizeof(SPatch));
require(patch, NewSysPtr);
patch->jump = JMP;
patch->where = routine;
patch->trap = theTrap;
patch->routine = *oldRoutine;
FlushInstructionRange(patch, sizeof(SPatch));
NSetTrapAddress((long)patch, theTrap, tType);
return (Patch)patch;
} else {
NSetTrapAddress((long)routine, theTrap, tType);
return (Patch)-1;
}
NewSysPtr:
TrapImplemented:
TrapEntryAvailable:
return nil;
}
/*<FF>*/
/**************************************************************************************
ROUTINE
RestoreTrap
DESCRIPTION
Given a patch as returned by PatchTrap, RestoreTrap will remove the patch.
**************************************************************************************/
void RestoreTrap(Patch patch)
{
TrapType trapType = GetTrapType(patch->trap);
/*
If the trap has been patched then change the jump vector to point to the
original routine. Otherwise set the trap address to point to the original
routine and dispose of the patch.
*/
if (NGetTrapAddress(((SPatch*)patch)->trap, trapType) != patch) {
((SPatch*)patch)->where = ((SPatch*)patch)->routine;
FlushInstructionRange(patch, sizeof(SPatch));
} else {
NSetTrapAddress((long)patch->routine, ((SPatch*)patch)->trap, trapType);
DisposePtr((Ptr)patch);
}
}